﻿Imports Microsoft.Office.Interop
Imports System.IO
Imports System.ComponentModel.DataAnnotations

Partial Public Class ExcelExporter(Of T)

    Public ReadOnly Property Output(ByVal base As IEnumerable(Of T), outfile As String) As FileInfo
        Get
            Dim baseType As Type = base.GetType.GetGenericArguments(0)
            Dim baseatt As ExportEntityAttribute = (From a In baseType.GetCustomAttributes(True) Where TypeOf a Is ExportEntityAttribute Select a).FirstOrDefault
            Dim metaatt As MetadataTypeAttribute = (From a In baseType.GetCustomAttributes(True) Where TypeOf a Is MetadataTypeAttribute Select a).FirstOrDefault

            If baseatt Is Nothing And metaatt Is Nothing Then Throw New Exception("ExportEntity is missing")
            If Not metaatt Is Nothing Then
                baseatt = (From a In metaatt.MetadataClassType.GetCustomAttributes(True) Where TypeOf a Is ExportEntityAttribute Select a).FirstOrDefault
            End If

            Dim rootNode As ExportTreeNode = RecursiveExportTree(New ExportTreeNode With {.MemberAtt = New ExportMemberAttribute(baseatt)}, baseType, metaatt)
            Dim maxdepth As Integer = RecursiveTreeMaxDepth(rootNode, 0)

            If rootNode.Nodes.Count = 0 Then Throw New Exception("No entity member is flagged for export")

            Dim excelApp As Excel.Application = Nothing
            Dim wb As Excel.Workbook
            Dim ws As Excel.Worksheet

            Try
                excelApp = New Excel.Application
                wb = excelApp.Workbooks.Add()
                ws = CType(wb.Sheets.Add(), Excel.Worksheet)
                ws.Name = baseatt.WorkSheetName


                For Each wbd As Excel.Worksheet In wb.Worksheets
                    If wbd.Name = ws.Name Then Continue For
                    wbd.Delete()
                Next

                Dim hlp As LastPosition = RecursiveHeaderRender(ws, New LastPosition(1, 1), rootNode, maxdepth, baseatt)

                Dim ilp As New LastPosition
                Dim lr As Integer = maxdepth + 1

                For Each item In base
                    ilp = RecursiveItemRender(ws, item, New LastPosition(lr, 1), rootNode, baseatt)
                    lr += 1
                Next

                For c As Integer = 1 To hlp.Column - 1
                    CType(ws.Columns(c), Excel.Range).AutoFit()
                Next

                excelApp.DisplayAlerts = False
                wb.SaveAs(outfile)

                Return New FileInfo(outfile)
            Catch ex As Exception
                Throw ex
            Finally
                ws = Nothing
                wb = Nothing

                excelApp.Quit()
                excelApp = Nothing
            End Try
            Return Nothing
        End Get
    End Property

End Class